
package com.epam.video.test;

import com.epam.android.widget.CheckpointSeekBar;
import com.epam.android.widget.CheckpointSeekBar.OnCheckpointSeekBarChangeListener;
import com.epam.video.entities.Answer;
import com.epam.video.entities.Ivc;
import com.epam.video.entities.Si;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class VideoActivity extends Activity implements OnCompletionListener, OnPreparedListener,
    OnVideoSizeChangedListener, OnErrorListener, SurfaceHolder.Callback {
  public static final String IVC_LECTION_ID_EXTRA = "ivc_lection_id_extra";

  public static final String IVC_ID_EXTRA = "ivc_id_extra";

  public static final String IVCS_JSON_EXTRA = "ivc_json_extra";

  private static final String TAG = "MediaPlayerDemo";

  private int videoWidth;

  private int videoHeight;

  private MediaPlayer mediaPlayer;

  private SurfaceView mPreview;

  private SurfaceHolder holder;

  private boolean isVideoSizeKnown = false;

  private boolean isVideoReadyToBePlayed = false;

  private Ivc ivc;

  private List<Ivc> listOfIvcs;

  private AsyncTask<Void, Void, Void> loadDataTask;

  private String siUrl;

  CheckpointSeekBar seekBar;

  Runnable seekBarUpdater = new Runnable() {

    @Override
    public void run() {
      if (mediaPlayer != null) {
        seekBar.setProgressAfterCheckpoint(mediaPlayer.getCurrentPosition());
        if (mediaPlayer.isPlaying()) {
          seekBar.postDelayed(seekBarUpdater, 100);
        }
      }
    }
  };

  // Interaction's variables
  private Si si;

  private Button selectButton;

  private ListView listView;

  private ArrayAdapter<String> listViewAdapter;

  private int checkedPosition = -1;

  private int currentDialogId = -1;

  private int seekTo = -1;

  /**
   * Called when the activity is first created.
   */
  @Override
  public void onCreate(final Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.media_player);
    mPreview = (SurfaceView) findViewById(R.id.surface);
    holder = mPreview.getHolder();
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    loadData();
    String ivcsListJson = getIntent().getStringExtra(IVCS_JSON_EXTRA);
    listOfIvcs = JsonParserUtils.getListOfIvcs(ivcsListJson);
    seekBar = (CheckpointSeekBar) findViewById(R.id.checkpointSeekBar);
    Integer total = 0;
    final Map<Integer, String> ivcMap = new HashMap<Integer, String>();
    List<Integer> checkpoints = new ArrayList<Integer>();
    for (Ivc i : listOfIvcs) {
      ivcMap.put(total, i.getId());
      total += i.getDuration();
      checkpoints.add(total);
    }

    seekBar.setCheckpoints(checkpoints);
    seekBar.setNotPassedCheckpointNumber(1);
    seekBar.setMax(total);
    seekBar.setProgress(0);
    seekBar.setOnCheckpointSeekBarChangeListener(new OnCheckpointSeekBarChangeListener() {

      int lastCheckPoint = 0;

      @Override
      public void onCheckPointReached(final int reachedCheckPoint, final int progressAfterCheckpoint) {

      }

      @Override
      public void onNotPassedCheckPointReached(final int notPassedCheckpointNumber) {
        // TODO show SI here
        mediaPlayer.stop();
        String nextUrl = ivc.getNextUrl();
        Log.i("D", "onNotPassedCheckPointReached " + nextUrl);
        if (nextUrl.contains(AppConstants.IS)) {
          siUrl = ivc.getNextUrl();
          openInteractionDialog();
        } else {
          seekBar.passCheckpoint();
        }
      }

      @Override
      public void onProgressChanged(final int reachedCheckPoint, final int progressAfterCheckpoint,
          final boolean fromUser) {
        // Log.i("D", "reached" + reachedCheckPoint + "_" + lastCheckPoint);
        if (lastCheckPoint != reachedCheckPoint) {
          lastCheckPoint = reachedCheckPoint;
          ivc = getIvc(ivcMap.get(reachedCheckPoint));
          seekTo = progressAfterCheckpoint;
          preparePlayer(ivc.getUrl());
        } else if (fromUser) {
          // Log.i("D", progressAfterCheckpoint + "-" +
          // mediaPlayer.getCurrentPosition());
          mediaPlayer.seekTo(progressAfterCheckpoint);
        }
      }
    });
  }

  private void preparePlayer(final Uri uri) {
    doCleanUp();
    mediaPlayer.reset();
    changePlayerDatasource(uri);
    mediaPlayer.prepareAsync();
  }

  private void loadData() {
    final String ivcId = getIntent().getStringExtra(IVC_ID_EXTRA);
    loadDataTask = new AsyncTask<Void, Void, Void>() {
      @Override
      protected Void doInBackground(final Void... params) {
        ivc = getIvc(ivcId);
        return null;
      }

      @Override
      protected void onPostExecute(final Void result) {
        super.onPostExecute(result);
        playVideo();
      }
    }.execute(null);
  }

  private Ivc getIvc(final String ivcId) {
    String lectionId = getIntent().getStringExtra(IVC_LECTION_ID_EXTRA);
    String ivcJson = HttpUtils.executeRequest(String.format(AppConstants.IVC_URL_FORMAT, lectionId, ivcId));
    return JsonParserUtils.parseIvc(ivcJson);
  }

  private Si getSi(final String siUrl) {
    String siJson = HttpUtils.executeRequest(siUrl);
    return JsonParserUtils.parseSi(siJson);
  }

  @Override
  public void onCompletion(final MediaPlayer arg0) {
    Log.d(TAG, "onCompletion called");

  }

  private void openInteractionDialog() {
    loadDataTask = new AsyncTask<Void, Void, Void>() {
      @Override
      protected Void doInBackground(final Void... params) {
        si = getSi(siUrl);
        return null;
      }

      @Override
      protected void onPostExecute(final Void result) {
        super.onPostExecute(result);
        currentDialogId = (int) System.currentTimeMillis();
        siUrl = ivc.getNextUrl();
        showDialog(currentDialogId);
      }
    }.execute(null);
  }

  private void initAndShowDialog(final Si siItem) {

    // dialog.show();
  }

  @Override
  protected Dialog onCreateDialog(final int id) {
    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
    View view = getLayoutInflater().inflate(R.layout.interaction_layout, null);
    initListView(view);
    initData(si);

    dialogBuilder.setTitle(si.getQuestion());
    dialogBuilder.setView(view);
    AlertDialog dialog = dialogBuilder.create();
    initSelectAnswerButton(dialog, view);
    return dialog;
  }

  private void initListView(final View rootView) {
    listViewAdapter = new ArrayAdapter<String>(this, R.layout.interaction_answer_layout);
    listView = (ListView) rootView.findViewById(R.id.interaction_answers_listview);
    listView.setAdapter(listViewAdapter);
    listView.setItemsCanFocus(false);
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    listView.setOnItemClickListener(new OnItemClickListener() {
      @Override
      public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
        checkedPosition = position;
      }
    });
  }

  private void initData(final Si siItem) {
    if (siItem != null) {
      List<String> answers = siItem.getAnswers();
      for (String answer : answers) {
        listViewAdapter.add(answer);
      }
      if (checkedPosition >= 0) {
        listView.setSelection(checkedPosition);
      }
    }
  }

  private void initSelectAnswerButton(final AlertDialog dialog, final View rootView) {
    selectButton = (Button) rootView.findViewById(R.id.select_answer);
    selectButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(final View v) {
        dismissDialog(currentDialogId);
        handleAnswer();
      }
    });
  }

  private void handleAnswer() {
    int checkedPosition = listView.getCheckedItemPosition();
    if (checkedPosition >= 0 && checkedPosition < si.getAnswers().size()) {

      String sendAnswerUrl = siUrl + String.format(AppConstants.SEND_ANSWER_URL_FORMAT, "" + (checkedPosition + 1));
      String answerJson = HttpUtils.executeRequest(sendAnswerUrl);
      Answer item = JsonParserUtils.parseAnswer(answerJson);
      if (item != null) {
        if (item.getNextUrl().contains(AppConstants.IS)) {
          siUrl = item.getNextUrl();
          si = getSi(siUrl);
          currentDialogId = (int) System.currentTimeMillis();
          showDialog(currentDialogId);
        } else {
          seekBar.passCheckpoint();
        }
      }
    }
  }

  @Override
  public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
    Log.v(TAG, "onVideoSizeChanged called");
    if (width == 0 || height == 0) {
      Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
      return;
    }
    isVideoSizeKnown = true;
    videoWidth = width;
    videoHeight = height;
    if (isVideoReadyToBePlayed && isVideoSizeKnown) {
      startVideoPlayback();
    }
  }

  @Override
  public void onPrepared(final MediaPlayer mediaplayer) {
    Log.d(TAG, "onPrepared called");
    isVideoReadyToBePlayed = true;
    if (isVideoReadyToBePlayed && isVideoSizeKnown) {
      startVideoPlayback();
      seekBar.postDelayed(seekBarUpdater, 33);
    }
  }

  @Override
  public void surfaceChanged(final SurfaceHolder surfaceholder, final int i, final int j, final int k) {
    Log.d(TAG, "surfaceChanged called");

  }

  @Override
  public void surfaceDestroyed(final SurfaceHolder surfaceholder) {
    Log.d(TAG, "surfaceDestroyed called");
  }

  @Override
  public void surfaceCreated(final SurfaceHolder holder) {
    Log.d(TAG, "surfaceCreated called");
    // playVideo();
  }

  @Override
  protected void onPause() {
    super.onPause();
    releaseMediaPlayer();
    doCleanUp();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    releaseMediaPlayer();
    doCleanUp();
  }

  private void playVideo() {
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setDisplay(holder);
    mediaPlayer.setOnCompletionListener(this);
    mediaPlayer.setOnPreparedListener(this);
    mediaPlayer.setOnErrorListener(this);
    mediaPlayer.setOnVideoSizeChangedListener(this);
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    preparePlayer(ivc.getUrl());
  }

  private void changePlayerDatasource(final Uri uri) {
    try {
      mediaPlayer.setDataSource(getApplicationContext(), uri);
    } catch (IllegalStateException e) {
      // see http://code.google.com/p/android/issues/detail?id=957
      mediaPlayer.reset();
      changePlayerDatasource(uri);
    } catch (Exception e) {
      Log.e("D", "error: " + e.getMessage(), e);
    }
  }

  private void releaseMediaPlayer() {
    if (mediaPlayer != null) {
      mediaPlayer.release();
      mediaPlayer = null;
    }
  }

  private void doCleanUp() {
    videoWidth = 0;
    videoHeight = 0;
    isVideoReadyToBePlayed = false;
    isVideoSizeKnown = false;
  }

  private void startVideoPlayback() {
    Log.v(TAG, "startVideoPlayback");
    holder.setFixedSize(videoWidth, videoHeight);
    if (seekTo != -1) {
      mediaPlayer.seekTo(seekTo);
      seekTo = -1;
    }
    mediaPlayer.start();
  }

  @Override
  public boolean onError(final MediaPlayer mp, final int what, final int extra) {
    return false;
  }
}
